package com.sh.data.engine.application.service.api;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.sh.data.engine.application.model.dto.api.DataApiBaseResponse;
import com.sh.data.engine.application.model.dto.api.DataApiResponse;
import com.sh.data.engine.application.model.dto.api.TagResponse;
import com.sh.data.engine.application.model.dto.common.DirectoryResponse;
import com.sh.data.engine.application.model.request.api.DataApiMyApiByTagRequest;
import com.sh.data.engine.application.model.request.api.DataApiMyApiRequest;
import com.sh.data.engine.application.model.request.api.DataApiTagDeleteRequest;
import com.sh.data.engine.application.model.request.api.DataApiTagSaveRequest;
import com.sh.data.engine.application.model.request.common.UpsertDirectoryRequest;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.api.model.domain.DataApiDomain;
import com.sh.data.engine.domain.api.model.domain.DataApiMyApiDomain;
import com.sh.data.engine.domain.api.model.domain.DataApiRegisterDomain;
import com.sh.data.engine.domain.api.model.domain.rest.DataApiTaskParamDomain;
import com.sh.data.engine.domain.api.model.param.DataApiMyApiParam;
import com.sh.data.engine.domain.api.service.DataApiService;
import com.sh.data.engine.domain.base.model.PageResult;
import com.sh.data.engine.domain.base.model.UserContext;
import com.sh.data.engine.domain.base.model.enums.DirectoryMenuEnum;
import com.sh.data.engine.domain.base.model.enums.TagTypeEnum;
import com.sh.data.engine.domain.common.model.domain.DirectoryDomain;
import com.sh.data.engine.domain.common.model.domain.TagDomain;
import com.sh.data.engine.domain.common.model.param.UpsertDirectoryParam;
import com.sh.data.engine.domain.common.service.DirectoryService;
import com.sh.data.engine.domain.common.service.TagService;
import com.sh.data.engine.domain.util.ConvertUtil;
import com.sh.data.engine.domain.workspace.manager.model.domain.UserDomain;
import com.sh.data.engine.domain.workspace.manager.service.UserService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: mengzheng.mhc
 * @date: 2024/8/15 21:17
 */
@Slf4j
@Service
public class DataApiMyApiApplicationService {

    @Autowired
    private DirectoryService directoryService;

    @Autowired
    private UserService userService;

    @Autowired
    private DataApiService dataApiService;

    @Autowired
    private TagService tagService;

    public List<DirectoryResponse> getDirList(String search) {
        List<DirectoryDomain> dirList =
            directoryService.getDirList(ServletUtils.getProjectId(), DirectoryMenuEnum.API, search);
        return ConvertUtil.copyProperties(dirList, DirectoryResponse.class);
    }

    public List<DirectoryResponse> getTagList(String search) {
        List<DirectoryDomain> dirList =
            directoryService.getDirListWithOutTopLevel(
                ServletUtils.getProjectId(), DirectoryMenuEnum.API_TAG, search);
        return ConvertUtil.copyProperties(dirList, DirectoryResponse.class);
    }

    public boolean createApiTag(UpsertDirectoryRequest request) {
        if (Objects.isNull(request.getId()) && Objects.isNull(request.getPid())) {
            request.setPid(0L);
        }
        UpsertDirectoryParam param = Convert.convert(UpsertDirectoryParam.class, request);
        param.setProjectId(ServletUtils.getProjectId());
        param.setMenuCode(DirectoryMenuEnum.API_TAG.getCode());

        return directoryService.upsetDir(param);
    }

    public boolean deleteApiTag(DataApiTagDeleteRequest dataApiTagDeleteRequest) {
        tagService.deleteTag(ServletUtils.getProjectId(), dataApiTagDeleteRequest.getId());
        return true;
    }

    public List<TagResponse> getApiTagById(Long apiId) {
        List<TagDomain> tagListByApiId =
            tagService.getTagListByApiId(ServletUtils.getProjectId(), apiId);
        List<TagResponse> result = new ArrayList<>();
        for (TagDomain tagDomain : tagListByApiId) {
            TagResponse tagResponse = new TagResponse();
            tagResponse.setId(tagDomain.getTagId());
            tagResponse.setDirName(tagDomain.getTagName());
            tagResponse.setPid(tagDomain.getPid());
            result.add(tagResponse);
        }
        return result;
    }

    public boolean saveApiTagById(DataApiTagSaveRequest request) {
        tagService.saveApiTagById(
            request.getApiId(), request.getAddTagList(), request.getDeleteTagList());
        return true;
    }

    public PageResult<DataApiBaseResponse> getMyApiListByTag(DataApiMyApiByTagRequest dataApiMyApiRequest) {
        Long projectId = ServletUtils.getProjectId();
        String userId = UserContext.getUserId();
        UserDomain userInfo = UserContext.getUserInfo();
        String username;
        if (Objects.nonNull(userInfo)) {
            username = userInfo.getUserName();
        } else {
            UserDomain userById = userService.getUserById(userId);
            username = userById.getUserName();
        }

        Long tagId = dataApiMyApiRequest.getTagId();
        List<Long> tagBizIdList =
            tagService.getTagBizIdList(projectId, TagTypeEnum.API.getCode(), tagId);

        DataApiMyApiParam dataApiMyApiParam =
            ConvertUtil.copyProperties(dataApiMyApiRequest, DataApiMyApiParam.class);
        dataApiMyApiParam.setProjectId(projectId);
        dataApiMyApiParam.setUserId(userId);
        IPage<DataApiMyApiDomain> dataApiMyApiDomainPageResult =
            dataApiService.findMyDataApiListByIds(dataApiMyApiParam, username, tagBizIdList);

        return PageResult.copyPropertiesAndConvert(
            dataApiMyApiDomainPageResult, DataApiBaseResponse.class);
    }

    public boolean upsetDir(UpsertDirectoryRequest request) {
        UpsertDirectoryParam param = Convert.convert(UpsertDirectoryParam.class, request);
        param.setProjectId(ServletUtils.getProjectId());
        param.setMenuCode(DirectoryMenuEnum.API.getCode());

        return directoryService.upsetDir(param);
    }

    public boolean deleteDir(Long id) {
        return dataApiService.deleteDir(id);
    }

    public boolean removeDataApiById(Long id) {
        return dataApiService.removeDataApiById(id);
    }

    public DataApiResponse getDataApiDetailById(Long id) {
        DataApiDomain dataApiDomain = dataApiService.getDataApiDetailById(id);
        DataApiRegisterDomain apiRegisterDomain = dataApiDomain.getApiRegisterDomain();
        List<DataApiTaskParamDomain> apiParamDomainList = dataApiDomain.getApiParamEntityList();

        DataApiResponse dataApiResponse =
            ConvertUtil.copyProperties(dataApiDomain, DataApiResponse.class);
        dataApiResponse.setDataApiRegisterDomain(apiRegisterDomain);

        if (apiParamDomainList != null) {
            List<DataApiResponse.DataApiParamResponse> dataApiParamResponses =
                ConvertUtil.copyProperties(apiParamDomainList, DataApiResponse.DataApiParamResponse.class);
            Map<Integer, List<DataApiResponse.DataApiParamResponse>> collect =
                dataApiParamResponses.stream()
                    .collect(Collectors.groupingBy(DataApiResponse.DataApiParamResponse::getParamType));
            List<DataApiResponse.DataApiParamResponse> dataApiParamResponses1 = collect.get(0);
            List<DataApiResponse.DataApiParamResponse> dataApiParamResponses2 = collect.get(1);
            dataApiResponse.setOutputParamResponses(
                dataApiParamResponses2 == null ? new ArrayList<>() : dataApiParamResponses2);
            dataApiResponse.setInputParamResponses(
                dataApiParamResponses1 == null ? new ArrayList<>() : dataApiParamResponses1);
        }
        return dataApiResponse;
    }

    public void exportApi(String apiIds, HttpServletResponse response) {
        String userId = UserContext.getUserId();
        Long projectId = ServletUtils.getProjectId();

        if (StringUtils.isBlank(apiIds)) {
            throw new BusinessException("apiIds参数为空");
        }

        List<Long> ids =
            Lists.newArrayList(apiIds.split(",")).stream()
                .map(e -> Long.valueOf(e))
                .collect(Collectors.toList());
        dataApiService.exportApi(ids, userId, projectId, response);
    }

    public boolean unPublishApiById(Long id) {
        return dataApiService.cancalPublishApiById(id);
    }

    public boolean unPublishApiByIds(String ids) {
        if (StringUtils.isNotBlank(ids)) {
            List<Long> collect = Arrays.stream(ids.split(",")).map(Long::valueOf).collect(Collectors.toList());
            return dataApiService.cancalPublishApiByIds(collect);
        }
        return false;
    }

    public boolean publishApiById(Long id) {
        return dataApiService.publishApiById(id);
    }

    public boolean publishApiByIds(String ids) {
        if (StringUtils.isNotBlank(ids)) {
            List<Long> collect = Arrays.stream(ids.split(",")).map(Long::valueOf)
                .collect(Collectors.toList());
            return dataApiService.publishApiByIds(collect);
        }
        return false;
    }

    public PageResult<DataApiBaseResponse> getMyApiList(DataApiMyApiRequest dataApiMyApiRequest) {
        String groupId = dataApiMyApiRequest.getGroupId();

        List<Long> groupIds = Lists.newArrayList();

        if (StringUtils.isNotBlank(groupId)) {
            String[] split = groupId.split(",");
            groupIds = Arrays.stream(split).map(e -> Long.valueOf(e)).collect(Collectors.toList());
        }
        Long projectId = ServletUtils.getProjectId();
        String userId = UserContext.getUserId();
        UserDomain userInfo = UserContext.getUserInfo();
        String username;
        if (Objects.nonNull(userInfo)) {
            username = userInfo.getUserName();
        } else {
            UserDomain userById = userService.getUserById(userId);
            username = userById.getUserName();
        }
        DataApiMyApiParam dataApiMyApiParam =
            ConvertUtil.copyProperties(dataApiMyApiRequest, DataApiMyApiParam.class);
        dataApiMyApiParam.setProjectId(projectId);
        dataApiMyApiParam.setUserId(userId);
        IPage<DataApiMyApiDomain> dataApiMyApiDomainPageResult =
            dataApiService.findMyDataApiList(dataApiMyApiParam, username, groupIds);

        return PageResult.copyPropertiesAndConvert(
            dataApiMyApiDomainPageResult, DataApiBaseResponse.class);
    }
}
